package com.snapan.service;

import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.ResponseHeaderOverrides;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

/**
 * OSS服务类
 */
@Service
public class OssService {
    
    @Autowired
    private OSS ossClient;
    
    @Value("${oss.bucket-name}")
    private String bucketName;
    
    /**
     * 上传文件到OSS
     */
    public String uploadFile(MultipartFile file, String fileName) {
        try {
            // 设置文件元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            metadata.setContentType(file.getContentType());
            
            // 上传文件到OSS（不设置公共读权限，使用默认私有权限）
            ossClient.putObject(bucketName, fileName, file.getInputStream(), metadata);
            
            // 尝试设置公共读权限
            setObjectPublicRead(fileName);
            
            // 返回OSS访问URL
            return "https://" + bucketName + ".oss-cn-beijing.aliyuncs.com/" + fileName;
        } catch (IOException e) {
            throw new RuntimeException("OSS上传失败", e);
        }
    }
    
    /**
     * 上传文件流到OSS
     */
    public String uploadFile(InputStream inputStream, String fileName, String contentType, long contentLength) {
        try {
            // 设置文件元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(contentLength);
            metadata.setContentType(contentType);
            
            // 上传文件到OSS（不设置公共读权限，使用默认私有权限）
            ossClient.putObject(bucketName, fileName, inputStream, metadata);
            
            // 尝试设置公共读权限
            setObjectPublicRead(fileName);
            
            // 返回OSS访问URL
            return "https://" + bucketName + ".oss-cn-beijing.aliyuncs.com/" + fileName;
        } catch (Exception e) {
            throw new RuntimeException("OSS上传失败", e);
        }
    }
    
    /**
     * 删除OSS文件
     */
    public void deleteFile(String fileName) {
        try {
            ossClient.deleteObject(bucketName, fileName);
        } catch (Exception e) {
            throw new RuntimeException("OSS删除失败", e);
        }
    }
    
    /**
     * 生成带签名的下载URL
     * 用于访问私有文件
     */
    public String generateSignedUrl(String fileName, int expirationMinutes) {
        try {
            // 设置URL过期时间
            java.util.Date expiration = new java.util.Date();
            long expTimeMillis = expiration.getTime() + expirationMinutes * 60 * 1000;
            expiration.setTime(expTimeMillis);
            
            // 生成带签名的URL
            java.net.URL signedUrl = ossClient.generatePresignedUrl(bucketName, fileName, expiration);
            return signedUrl.toString();
        } catch (Exception e) {
            throw new RuntimeException("生成签名URL失败", e);
        }
    }
    
    /**
     * 生成带签名的下载URL（默认1小时有效期）
     */
    public String generateSignedUrl(String fileName) {
        return generateSignedUrl(fileName, 60); // 默认1小时
    }
    
    /**
     * 生成带签名的预览URL（用于在线预览）
     */
    public String generatePreviewUrl(String fileName, int expirationMinutes) {
        try {
            // 设置URL过期时间
            java.util.Date expiration = new java.util.Date();
            long expTimeMillis = expiration.getTime() + expirationMinutes * 60 * 1000;
            expiration.setTime(expTimeMillis);
            //创建响应头配置对象，控制浏览器是否预览
            ResponseHeaderOverrides headers=new ResponseHeaderOverrides();
            // 判断文件是否为PDF或Office文件，强制预览
            String lowerFileName = fileName.toLowerCase();
            if (lowerFileName.endsWith(".pdf") ||
                    lowerFileName.endsWith(".doc") ||
                    lowerFileName.endsWith(".docx") ||
                    lowerFileName.endsWith(".xls") ||
                    lowerFileName.endsWith(".xlsx") ||
                    lowerFileName.endsWith(".ppt") ||
                    lowerFileName.endsWith(".pptx")) {

                String fileNameOnly = fileName.substring(fileName.lastIndexOf("/") + 1);
                // 设置Content-Disposition为inline，允许浏览器预览
                headers.setContentDisposition("inline;filename=\"" + fileNameOnly + "\"");

            }
            //生成带响应头配置的签名url
            com.aliyun.oss.model.GeneratePresignedUrlRequest request=
                    new com.aliyun.oss.model.GeneratePresignedUrlRequest(bucketName,fileName);
            request.setExpiration(expiration);
            request.setMethod(HttpMethod.GET);
            request.setResponseHeaders(headers);
            // 生成带签名的URL，用于预览（GET请求）
            java.net.URL signedUrl = ossClient.generatePresignedUrl(request);
            String urlStr=signedUrl.toString();
            return urlStr;
        } catch (Exception e) {
            throw new RuntimeException("生成预览URL失败", e);
        }
    }
    
    /**
     * 检查文件是否存在
     */
    public boolean doesObjectExist(String fileName) {
        try {
            return ossClient.doesObjectExist(bucketName, fileName);
        } catch (Exception e) {
            System.out.println("检查文件存在性失败: " + e.getMessage());
            return false;
        }
    }
    
    /**
     * 设置文件为公共读（需要Bucket权限允许）
     */
    public void setObjectPublicRead(String fileName) {
        try {
            // 设置对象ACL为公共读
            ossClient.setObjectAcl(bucketName, fileName, com.aliyun.oss.model.CannedAccessControlList.PublicRead);
        } catch (Exception e) {
            System.out.println("设置公共读权限失败: " + e.getMessage());
            // 不抛出异常，继续使用签名URL
        }
    }
    
    /**
     * 生成唯一文件名
     */
    public String generateFileName(String originalFileName) {
        String extension = "";
        if (originalFileName != null && originalFileName.contains(".")) {
            extension = originalFileName.substring(originalFileName.lastIndexOf("."));
        }
        return UUID.randomUUID().toString().replace("-", "") + extension;
    }
}
